package pl.edu.agh.ros.node;

import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.ros.node.DefaultNodeFactory;
import org.ros.node.NodeConfiguration;
import org.ros.node.topic.Publisher;

import pl.edu.agh.ros.node.conf.ProxyNodeConfiguration;
import pl.edu.agh.ros.node.conf.XMPPConfiguration;
import pl.edu.agh.ros.node.manager.IServerManager;
import pl.edu.agh.ros.node.manager.XMPPManager;
import pl.edu.agh.ros.node.prop.Props;
import pl.edu.agh.ros.node.util.RosMessageUtils;

import com.google.common.base.Preconditions;

public class ProxyPublisher<T extends org.ros.message.Message> extends AbstractProxyNode {

	protected final RosMessageUtils<T> rosMessageUtils;
	private Publisher<T> publisher;

	public ProxyPublisher(IServerManager serverManager, XMPPConfiguration xmppConfiguration,
			ProxyNodeConfiguration proxyNodeConfiguration, String nodeName) {
		super(serverManager, xmppConfiguration, proxyNodeConfiguration, nodeName);
		this.rosMessageUtils = new RosMessageUtils<T>();
	}

	@Override
	public void main(NodeConfiguration nodeConfiguration) throws Exception {
		Preconditions.checkState(node == null);
		Preconditions.checkNotNull(nodeConfiguration);

		try {
			xmppConnector = new XMPPManager();
			xmppConnector.connectAndLogin(xmppConfiguration);
			node = new DefaultNodeFactory().newNode(nodeName, nodeConfiguration);
			publisher = node.newPublisher(proxyNodeConfiguration.getName(), proxyNodeConfiguration.getType());
			createXMPPPacketListener();
			// TODO change to log4j
			System.out.println("ProxyPublisher running"); //$NON-NLS-1$
		} catch (Exception e) {
			if (node != null) {
				node.getLog().fatal(e);
			} else {
				e.printStackTrace();
			}
		}

	}

	protected void onXMPPMessage(Message message) {
		if (message.getProperty(Props.XMPP_MSG_TYPE).equals(proxyNodeConfiguration.getType())) {
			T rosMessage = rosMessageUtils.deserializeMessage(message, node, proxyNodeConfiguration.getType());
			publisher.publish(rosMessage);
		}
	}

	private void createXMPPPacketListener() {
		PacketListener packetListener = new PacketListener() {
			public void processPacket(Packet packet) {
				if (packet instanceof Message) {
					Message message = (Message) packet;
					onXMPPMessage(message);
				}
			}
		};
		xmppConnector.getConnection().addPacketListener(packetListener, null);
	}

}
